


// ========== 全局控制按钮 ==========

/**
* @brief 启用全部控制按钮
* 一键启用所有控制卡片
*/
document.addEventListener('DOMContentLoaded', function() {
    // 等待控制卡片初始化完成
    setTimeout(initGlobalControls, 300);
    initWebsocket();
    
});

function exitPanel() {
    window.location.href = "/";
}


// ========== 定时数据发送 ==========

/**
    * @brief 定期发送控制数据
    * 
    * 每100毫秒发送一次控制数据到后端
    */
// setInterval(sendControlData, 100);


// 初始话websocket连接
function initWebsocket() {

    // 连接切换按钮
    const connectToggle = document.getElementById("connection-toggle");
    // 连接状态文本(按钮右边的)
    const connectStatusText = document.getElementById("connect-status-text");
    // 连接状态元素  （按钮下面的大条子）
    const connectionStatus = document.getElementById('connection-status');  
    // ip禁用控制div
    const ipInputDiv = document.getElementById("ip-input") ;
    //  ip和端口输入框
    const ipAddressInput = document.getElementById('ip-address');
    const portNumberInput = document.getElementById('port-number');

    isConnected = false;

    setInterval(sendControlData, 100);


    // 添加连接开关按钮的触发事件
    connectToggle.addEventListener('change', function() {
        if (this.checked) {
            connect();
        } else {
            // 断开前转换为显示模式
            document.getElementById("panel-mode-toggle").checked = false;
            document.getElementById("panel-mode-text").textContent = "显示";
            // 睡眠0.2秒，等显示模式发送到后端
            setTimeout(() => {
                disconnect();
            }, 200);
        }
    });

    /**
     * @brief 验证IP地址格式
     * @param {string} ip - IP地址字符串
     * @returns {boolean} - 是否为有效的IP地址
     */
    function validateIPAddress(ip) {
        if (!ip || ip.trim() === '') {
            return false;
        }
        
        // IPv4地址正则表达式
        const ipv4Regex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
        
        // 支持localhost
        if (ip.toLowerCase() === 'localhost') {
            return true;
        }

        return ipv4Regex.test(ip) ;
    }

    /**
     * @brief 验证端口号
     * @param {string|number} port - 端口号
     * @returns {boolean} - 是否为有效的端口号
     */
    function validatePort(port) {
        const portNum = parseInt(port);
        return !isNaN(portNum) && portNum >= 1 && portNum <= 65535;
    }


    // ========== WebSocket连接管理 ==========  
    let socket;  // WebSocket连接对象  

    /**  
     * @brief 建立WebSocket连接  
     *   
     * 尝试连接到多个可能的服务器地址：  
     * 1. 10.21.103.150:8080 (指定的服务器地址)  
     * 2. localhost:8080 (本地环回)  
     * 3. 127.0.0.1:8080 (本地IP)  
     *   
     * 如果一个地址失败，自动尝试下一个地址  
     * 连接失败后会自动重连  
     */  
    function connect() {  
        // 定义多个备选服务器地址  
        // const serverAddresses = [  
        //     'ws://10.21.162.157:8080'  // 主服务器地址  
        // ];  

        // 获取输入ip和端口
        const ip = ipAddressInput.value.trim();
        const port = portNumberInput.value.trim();

        // 验证输入
        if (!validateIPAddress(ip)) {
            connectStatusText.textContent = "无效输入";
            console.log("ip无效: ",ip);
            setTimeout(() => {connectStatusText.className = 'invalid'}, 100); // 闪一下
            connectStatusText.className = "disconnected"; 
            connectToggle.checked = false;
            ipInputDiv.className = 'control-enabled'
            return;
        }
        if (!validatePort(port)) {
            connectStatusText.textContent = "无效输入";
            console.log("端口无效: ",port);
            setTimeout(() => {connectStatusText.className = 'invalid'}, 100); // 闪一下
            connectStatusText.className = "disconnected"; 
            connectToggle.checked = false;
            ipInputDiv.className = 'control-enabled'
            return;
        }

        // connectStatusText.textContent = "已输入"

        const wsUrl = `ws://${ip}:${port}`;
        const serverAddresses = [
            wsUrl
        ];

        let currentAddressIndex = 0;  // 当前尝试的地址索引  
        
        /**  
         * @brief 尝试连接到当前索引的服务器地址  
         */  
        function tryConnect() {  
            // 如果所有地址都尝试失败，重置索引并延迟重连  
            if (currentAddressIndex >= serverAddresses.length) {  
                console.error("所有服务器地址都无法连接");  
                connectionStatus.textContent = "连接失败";  
                connectionStatus.className = "connection-status disconnected";  
                currentAddressIndex = 0;  // 重置索引  
                console.log("ip数量：",serverAddresses.length);
                setTimeout(connect, 2000);  // 2秒后重新尝试  
                return;  
            }  
            
            const wsUrl = serverAddresses[currentAddressIndex];  
            console.log(`尝试连接到: ${wsUrl}`);  
            connectionStatus.textContent = `连接中... (${wsUrl})`;  
            
            // 创建WebSocket连接  
            socket = new WebSocket(wsUrl);  
        
            /**  
             * @brief WebSocket连接成功事件处理  
             */  
            socket.onopen = function(e) {  
                console.log(`连接已建立: ${wsUrl}`);  
                isConnected = true;  
                connectStatusText.textContent = "已连接";
                connectStatusText.className = "connected";
                ipInputDiv.className = 'control-disabled'
                connectionStatus.textContent = `已连接 (${wsUrl})`;  
                connectionStatus.className = "connection-status connected";  
            };  
            
            /**  
             * @brief WebSocket连接关闭事件处理  
             */  
            socket.onclose = function(e) {  
                console.log(`连接已关闭: ${wsUrl}`);  
                isConnected = false;  

                connectStatusText.textContent = "未连接";
                connectStatusText.className = "disconnected";
                ipInputDiv.className = 'control-enabled'
                connectToggle.checked = false;
                connectionStatus.textContent = `连接中断 (${wsUrl})`;
                connectionStatus.className = "connection-status disconnected";  
                currentAddressIndex++;  // 尝试下一个地址  
            };  
            
            /**  
             * @brief WebSocket连接错误事件处理  
             */  
            socket.onerror = function(error) {  
                console.error(`WebSocket错误 (${wsUrl}):`, error);  
                currentAddressIndex++;  // 尝试下一个地址  
                connectionStatus.textContent = "连接中断"; 
            };  
            
            /**  
             * @brief WebSocket消息接收事件处理 
             *   
             * 处理来自C++后端的消息：  
             * - 控制命令确认  
             * - 车辆状态更新  
             * - 服务器状态信息  
             */  
            socket.onmessage = function(event) {  
                // TODO: 这里可以添加处理来自后端的状态更新消息  
                // 例如：实时显示车辆状态、处理服务器响应等  
                try {  
                    const message = JSON.parse(event.data);  
                    // console.log("收到消息:", message);      
                    
                    // 根据消息类型处理不同的消息  
                    switch(message.type) {  
                        case 'vehicle_status':  
                            // 处理车辆状态消息  
                            updateVehicleStatusDisplay(message);  
                            updateChartData(message);
                            console.log("收到车辆状态消息:", message);
                            break;  
                        case 'welcome':  
                            // 处理欢迎消息  
                            console.log('服务器欢迎消息:', message.message);  
                            break;  
                            
                        case 'received':  
                            // 处理控制命令确认消息  
                            console.log('控制命令已确认:', message.echo);  
                            break;  
                            
                        case 'error':  
                            // 处理错误消息  
                            console.error('服务器错误:', message.message);  
                            break;  
                            
                        default:  
                            console.log('未知消息类型:', message.type);  
                    }  
                } catch (error) {  
                    console.error('解析WebSocket消息时出错:', error);  
                    console.log('原始消息:', event.data);  
                }  
            };  

        }  
        
        tryConnect();  // 开始尝试连接  
    }  

    /**
    * @brief 断开WebSocket连接
    */
    function disconnect() {
        if (socket && socket.readyState === WebSocket.OPEN) {
            socket.close(1000, 'User disconnected'); // 正常关闭
        }
        
        socket = null;
        isConnected = false;
        // updateStatus('未连接', 'disconnected');

        connectStatusText.textContent = "未连接";
        connectStatusText.className = "disconnected"; 
        connectionStatus.textContent = "未连接";
        connectionStatus.className = "connection-status disconnected";
        connectToggle.checked = false;
        ipInputDiv.className = 'control-enabled'
    }


    // ========== 数据发送功能 ==========  
    /**  
    * @brief 发送控制数据到C++后端  
    *   
    * 构建包含所有控制信息的JSON对象并发送给后端：  
    * - 油门、刹车、方向盘、挡位、灯光的当前值  
    * - 各控制器的启用状态  
    * - 驾驶模式信息  
    * - 时间戳  
    */  
    function sendControlData() {  
        if (!isConnected) return;  
        
        // 获取所有卡片的控制值
        const controlData = window.getControlCardValues();

        // 增加panelMode字段
        controlData.panelMode = document.getElementById('panel-mode-toggle').checked? 'control':'display';

        console.log('controlData'+JSON.stringify(controlData));
        // console.log('controlData',(controlData));

        // 发送JSON数据到后端  
        socket.send(JSON.stringify(controlData));  
    }  

}

function showOutput() {
    const controlData = window.getControlCardValues();
    layer.prompt({
        title: '输出',
        formType: 2,
        area: ['600px', '400px'],
        value: JSON.stringify(controlData, null, 2),
        maxlength: 20000,
        btn: ['确定']
    }, function(value, index, elem){
        layer.close(index);
    });
}



function initGlobalControls() {
    const enableAllBtn = document.getElementById('enable-all-btn');
    const disableAllBtn = document.getElementById('disable-all-btn');
    const configLoadBtn = document.getElementById('config-load-btn');
    const configFileInput = document.getElementById('configFileInput');


    // 全部启用按钮
    enableAllBtn.addEventListener('click', function() {
        handleEnableAll(true);
    });

    // 全部禁用按钮
    disableAllBtn.addEventListener('click', function() {
        handleEnableAll(false);
    });

    // 配置加载按钮
    configLoadBtn.addEventListener('click', function() {
        configFileInput.click();
    });

    // 配置文件选择
    configFileInput.addEventListener('change', function(e) {
        loadConfigFromFile(e);
    });



    // 处理全部启用/禁用
    function handleEnableAll(enable) {
        const controlCards = document.querySelectorAll('.control-card');
        controlCards.forEach(card => {
            if (card.setEnable) {
                card.setEnable(enable);
            }
        });
    }

}

// 面板模式切换
const panelModeToggle = document.getElementById("panel-mode-toggle");
const panelModeText = document.getElementById("panel-mode-text");
panelModeToggle.addEventListener("change", function() {
    if (panelModeToggle.checked) {
        panelModeText.textContent = "控制";
    } else {
        panelModeText.textContent = "展示";
    }
});



// ========== 新增：车辆状态显示元素 ==========  
//  ip和端口输入
const ipAddressInput = document.getElementById('ip-address');
const portNumberInput = document.getElementById('port-number');
const connectButton = document.getElementById('connect-button');
const resetButton = document.getElementById('reset-button');

// 底盘状态元素  
const statusSpeed = document.getElementById('status-speed');  
const statusSteeringAngle = document.getElementById('status-steering-angle');  
const statusGear = document.getElementById('status-gear');  
const statusBrakePedal = document.getElementById('status-brake-pedal');  
const statusThrottlePedal = document.getElementById('status-throttle-pedal');  

// 物理输入元素
const throttleInput = document.getElementById('throttle-input');
const brakeInput = document.getElementById('brake-input');
const steeringInput = document.getElementById('steering-input');
const gearInput = document.getElementById('gear-input');

// 程序输入元素
const throttleCommand = document.getElementById('throttle-command');
const brakeCommand = document.getElementById('brake-command');
const steeringCommand = document.getElementById('steering-command');
const gearCommand = document.getElementById('gear-command');
const gearReject = document.getElementById('gear-reject');

// 接管状态元素
const throttleOverride = document.getElementById('throttle-override');
const brakeOverride = document.getElementById('brake-override');
const steeringOverride = document.getElementById('steering-override');
const gearOverride = document.getElementById('gear-override');

// 握手状态元素  
const throttleHandshake = document.getElementById('throttle-handshake');
const brakeHandshake = document.getElementById('brake-handshake');
const steeringHandshake = document.getElementById('steering-handshake');
const gearHandshake = document.getElementById('gear-handshake');


// 控制状态元素  
const controlThrottleStatus = document.getElementById('control-throttle-status');  
const controlBrakeStatus = document.getElementById('control-brake-status');  
const controlSteeringStatus = document.getElementById('control-steering-status');  
const controlGearStatus = document.getElementById('control-gear-status');  
const controlDrivingMode = document.getElementById('control-driving-mode');  

// websocket系统状态元素  
const serverStatus = document.getElementById('server-status');  
const connectedClients = document.getElementById('connected-clients');  
const dataSequence = document.getElementById('data-sequence');  
const lastUpdate = document.getElementById('last-update');  
const panelMode = document.getElementById('panel-mode');
// 更新图表信息
function updateChartData(statusData) {
    const data = statusData.html_report;
    if (window.ChartsAPI && window.ChartsAPI.isReady()) {

        window.ChartsAPI.addMultiData('comprehensive-chart', {
            '方向盘角度': data.steering_commend,
            '油门': data.throttle_commend,
            '刹车': data.brake_commend,
        });

        window.ChartsAPI.addData('chart-1', statusData.chassis.throttle.pedal_input );
        window.ChartsAPI.addData('chart-2',statusData.chassis.brake.pedal_input );
        window.ChartsAPI.addData('chart-3',statusData.chassis.steering.steering_wheel_torque_report);
        
    } else{
        console.log("图表未初始化");
    }
}

// ========== 车辆状态更新函数 ==========  

/**  
 * @brief 更新车辆状态显示  
 * @param {Object} statusData - 从WebSocket接收的状态数据  
 *   
 * 解析并显示车辆状态信息，包括：  
 * - 底盘状态（车速、方向盘、挡位、刹车、油门）  
 * - 车身状态（车门、灯光）  
 * - 控制状态（各控制器启用状态）  
 * - websocket系统状态（服务器状态、连接数）  
 */  
function updateVehicleStatusDisplay(statusData) {  
    try {  
        // ========== 更新底盘状态 ==========  
        if (statusData.chassis) {  
            const chassis = statusData.chassis;  
            
            // 更新车速  
            if (chassis.speed) {  
                const speed = chassis.speed.vehicle_speed;  
                const speedValid = chassis.speed.speed_valid;  
                statusSpeed.textContent = speedValid ?   
                    `${speed.toFixed(2)} m/s` :   
                    'N/A';  
                statusSpeed.className = speedValid ? 'status-value' : 'status-value status-invalid';  
            }  
            
            // 更新方向盘转角  
            if (chassis.steering) {  
                const angle = chassis.steering.angle;  
                const angleValid = chassis.steering.angle_valid;  
                statusSteeringAngle.textContent = angleValid ?   
                    `${angle.toFixed(1)}°` :   
                    'N/A';  
                statusSteeringAngle.className = angleValid ? 'status-value' : 'status-value status-invalid';  
            }  
            
            // 更新挡位  
            if (chassis.gear) {  
                const gear = chassis.gear.current_gear;  
                const gearValid = chassis.gear.gear_valid;  
                statusGear.textContent = gearValid ? gear : 'N/A';  
                statusGear.className = gearValid ? 'status-value' : 'status-value status-invalid';  

                if (gear==1)
                    statusGear.textContent = "P";
                else if (gear==2)
                    statusGear.textContent = "R";
                else if (gear==3)
                    statusGear.textContent = "N";
                else if (gear==4)
                    statusGear.textContent = "D";
                else
                    statusGear.textContent = "N/A";
            }  
            
            // 更新刹车踏板  
            if (chassis.brake) {  
                const brake = chassis.brake.brake_pedal;  
                const brakeValid = chassis.brake.brake_valid;  
                statusBrakePedal.textContent = brakeValid ?   
                    `${brake.toFixed(1)}%` :   
                    'N/A';  
                statusBrakePedal.className = brakeValid ? 'status-value' : 'status-value status-invalid';  
            }  
            
            // 更新油门踏板  
            if (chassis.throttle) {  
                const throttle = chassis.throttle.throttle_pedal;  
                const throttleValid = chassis.throttle.throttle_valid;  
                statusThrottlePedal.textContent = throttleValid ?   
                    `${throttle.toFixed(1)}%` :   
                    'N/A';  
                statusThrottlePedal.className = throttleValid ? 'status-value' : 'status-value status-invalid';  
            }  


            // 更新物理输入：油门
            throttleInput.textContent = chassis.throttle.pedal_input.toFixed(2);

            // 更新物理输入：刹车
            brakeInput.textContent = chassis.brake.pedal_input.toFixed(2);

            // 更新物理输入：方向盘
            steeringInput.textContent = chassis.steering.steering_wheel_torque_report.toFixed(2);

            // 更新物理输入：挡位
            if (chassis.gear.pedal_input==1)
                gearInput.textContent = "P";
            else if (chassis.gear.pedal_input==2)
                gearInput.textContent = "R";
            else if (chassis.gear.pedal_input==3)
                gearInput.textContent = "N";
            else if (chassis.gear.pedal_input==4)
                gearInput.textContent = "D";
            else
                gearInput.textContent = "N/A";
            
            // 更新程序输入：油门
            throttleCommand.textContent = chassis.throttle.command.toFixed(2);
            
            // 更新程序输入：刹车
            brakeCommand.textContent = chassis.brake.command.toFixed(2);;
            
            // 更新程序输入：方向盘
            steeringCommand.textContent = chassis.steering.command.toFixed(2);;

            // 更新程序输入：挡位
            gearCommand.textContent = chassis.gear.command;

            // 更新程序输入：挡位拒绝
            gearReject.textContent = chassis.gear.reject;

            // 更新接管状态：油门
            throttleOverride.textContent = chassis.throttle.override;   
            throttleOverride.className = chassis.throttle.override ? 'status-enabled' : 'status-disabled';

            // 更新接管状态：刹车
            brakeOverride.textContent = chassis.brake.override;   
            brakeOverride.className = chassis.brake.override ? 'status-enabled' : 'status-disabled';

            // 更新接管状态：方向盘
            steeringOverride.textContent = chassis.steering.override;   
            steeringOverride.className = chassis.steering.override ? 'status-enabled' : 'status-disabled';

            // 更新接管状态：挡位
            gearOverride.textContent = chassis.gear.override;   
            gearOverride.className = chassis.gear.override ? 'status-enabled' : 'status-disabled';

            // 更新握手状态: 油门
            throttleHandshake.textContent = chassis.throttle.ready;   
            throttleHandshake.className = chassis.throttle.ready ? 'status-enabled' : 'status-disabled';

            // 更新握手状态：刹车
            brakeHandshake.textContent = chassis.brake.ready;   
            brakeHandshake.className = chassis.brake.ready ? 'status-enabled' : 'status-disabled';


            // 更新握手状态：方向盘
            steeringHandshake.textContent = chassis.steering.ready;   
            steeringHandshake.className = chassis.steering.ready ? 'status-enabled' : 'status-disabled';


            // 更新握手状态：挡位
            gearHandshake.textContent = chassis.gear.ready;   
            gearHandshake.className = chassis.gear.ready ? 'status-enabled' : 'status-disabled';


        }  
        
        // ========== 更新前端控制指令 ==========  
        if (statusData.html_report) {  
            const controlStatus = statusData.html_report;  
            
            // 更新各控制器启用状态  
            if (controlStatus.throttle_enabled !== undefined) {  
                const throttle_value = controlStatus.throttle_commend;
                controlThrottleStatus.textContent = controlStatus.throttle_enabled ? parseFloat(throttle_value).toFixed(2) +' | 启用' : '-- | 禁用';  
                controlThrottleStatus.className = controlStatus.throttle_enabled ? 'status-enabled' : 'status-disabled';  
            }  
            
            if (controlStatus.brake_enabled !== undefined) {  
                const brake_value = controlStatus.brake_commend;
                controlBrakeStatus.textContent = controlStatus.brake_enabled ? parseFloat(brake_value).toFixed(2) +' | 启用' : '-- | 禁用';  
                controlBrakeStatus.className = controlStatus.brake_enabled ? 'status-enabled' : 'status-disabled';  
            }  
            
            if (controlStatus.steering_enabled !== undefined) {  
                const steering_value = controlStatus.steering_commend;
                controlSteeringStatus.textContent = controlStatus.steering_enabled ? parseFloat(steering_value).toFixed(2) +' | 启用' : '-- | 禁用';  
                controlSteeringStatus.className = controlStatus.steering_enabled ? 'status-enabled' : 'status-disabled';  
            }  
            
            if (controlStatus.gear_enabled !== undefined) {  
                const gear_value = controlStatus.gear_commend;
                controlGearStatus.textContent = controlStatus.gear_enabled ? gear_value +' | 启用' : '-- | 禁用';  
                controlGearStatus.className = controlStatus.gear_enabled ? 'status-enabled' : 'status-disabled';  
            }  
            
            // 更新驾驶模式  
            if (controlStatus.driving_mode !== undefined) {  
                if (controlStatus.driving_mode === "driving") {
                    controlDrivingMode.textContent = '行车';
                    controlDrivingMode.style.color = '#ff9800';  // 橙色  
                } else if (controlStatus.driving_mode === "parking") {
                    controlDrivingMode.textContent = '泊车';
                    controlDrivingMode.style.color = '#4CAF50';  // 绿色
                } else if (controlStatus.driving_mode === "none") {
                    controlDrivingMode.textContent = "手动";
                    controlDrivingMode.className = 'status-value';  
                } else {
                    controlDrivingMode.textContent = 'N/A';
                    controlDrivingMode.className = 'status-invalid'
                }
                
            }  
        }  
        
        // ========== 更新websocket系统状态 ==========  
        if (statusData.websocket_status) {  
            const systemStatus = statusData.websocket_status;  
            
            // 更新服务器状态  
            if (systemStatus.server_running !== undefined) {  
                serverStatus.textContent = systemStatus.server_running ? '在线' : '离线';  
                serverStatus.className = systemStatus.server_running ? 'status-enabled' : 'status-disabled';  
            }  
            
            // 更新连接客户端数量  
            if (systemStatus.connected_clients !== undefined) {  
                connectedClients.textContent = systemStatus.connected_clients.toString();  
                connectedClients.className = 'status-value';  
            }  

            // 更新面板模式
            if (systemStatus.panel_mode !== undefined) {  
                panelMode.textContent = systemStatus.panel_mode;  
                panelMode.className = 'status-value';  
            }  
        }  
        
        // ========== 更新通用信息 ==========  
        
        // 更新数据序号  
        if (statusData.seq !== undefined) {  
            dataSequence.textContent = statusData.seq.toString();  
        }  
        
        // 更新时间戳  
        if (statusData.timestamp !== undefined) {  
            const date = new Date(statusData.timestamp * 1000);  
            lastUpdate.textContent = date.toLocaleTimeString();  
        }  
        
    } catch (error) {  
        console.error('更新车辆状态显示时发生错误:', error);  
    }  
}  

